package org.jsoncrypto.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class Compress {
	// based on code from http://stackoverflow.com/questions/6717165/how-can-i-zip-and-unzip-a-string-using-gzipoutputstream-that-is-compatible-with

	public static byte[] compress(byte[] bytes) throws IOException {
	    byte[] blockcopy = ByteBuffer
	        .allocate(4)
	        .order(java.nio.ByteOrder.LITTLE_ENDIAN)
	        .putInt(bytes.length)
	        .array();
	    ByteArrayOutputStream os = new ByteArrayOutputStream(bytes.length);
	    GZIPOutputStream gos = new GZIPOutputStream(os);
	    try {
		    gos.write(bytes);
	    } finally {
		    gos.close();
		    os.close();
	    }
	    byte[] ba = os.toByteArray();
	    byte[] compressed = new byte[4 + ba.length];
	    System.arraycopy(blockcopy, 0, compressed, 0, 4);
	    System.arraycopy(ba, 0, compressed, 4, ba.length);
	    return compressed;
	}

	public static byte[] decompress(byte[] compressed) throws IOException {
	    final int BUFFER_SIZE = 32;
	    ByteArrayInputStream is = new ByteArrayInputStream(compressed, 4, compressed.length - 4);
	    GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
	    try {
		    byte[] data = new byte[BUFFER_SIZE];
		    int r;
		    while ((r = gis.read(data)) > 0) {
		        baos.write(data, 0, r);
		    }
	    } finally {
		    gis.close();
		    is.close();
	    }
	    return baos.toByteArray();
	}
}
